//#define KP_UNIX
#ifdef KP_UNIX
	#include <sys/types.h>  
	#include <sys/socket.h>
	#include <netinet/in.h>
	#include <netdb.h>
	#include <unistd.h>
#else
	#include <windows.h>
#endif
#include <mpi.h>

#include <stdio.h>
#include "addon.h"
#include "innercommands.h"

#define MAXSS 4

int countCubNumber(int i, int j, int k, int edgeNumber, BigFilePointer *p1);
int countCubNumber2(int i, int j, int k, int edgeNumber, BigFilePointer *p1);

/***********
int   l_temp[100];
float x_temp[100];
float y_temp[100];
float z_temp[100];
int   links[2][50];
int   n_temp;
*/

int sendNcharBytes(int msgsock, char* buffer, int cSize)
{
#ifdef KP_UNIX
	#ifdef KP_BEMF
	swop(buffer, cSize);
	#endif
	return write(msgsock, buffer, cSize);
#else
	return send( msgsock, buffer, cSize, MSG_DONTROUTE);
#endif
}

int readNcharBytes(int msgsock, char *buffer, int cSize)
{
	int rval;
#ifdef KP_UNIX
	rval = read(msgsock, buffer, cSize);
	#ifdef KP_BEMF
	swop(buffer, cSize);
	#endif
#else
	rval=recv(msgsock,buffer,cSize,0);
#endif
	return rval;
}

void getGridName(char* s, char* gridname, char* gridFileName)
{
	int i,len;
	len=strlen(s);
	if(gridname[0]=='/')  /* grid Name has absolyte path */
	{
		strcpy(gridFileName, gridname);
		return;
	}
	for(i=len-1;i>0;i--)
	{
		if( (s[i]=='/') || (s[i]=='\\') )
		{
			strcpy(gridFileName, s);
			gridFileName[i+1]=0;
			strcpy(gridFileName+(i+1), gridname);
			gridFileName[i+1+strlen(gridname)]=0;
			return;
		}
	}
	strcpy(gridFileName, gridname);
	return;
};

int getFileInfo(char *s, BJN_INFO *bjn_info, FILE *debugFileOutput)
{
	int err;	
	err=ReadBjnGzippedScalar8RecInfo( s, bjn_info);
	//PrnBjnInfo(stdout, bjn_info);
	if(err) return err;
	return 0;
}
/**
 * E`ta procedura c`itaet ishodnye dannye iz fai`la v pama`tx
 */

int getFromFile(BigFilePointer *p1, char *s, char *f, BJN_INFO *bjn_info)
{
#if 0
	int err;	
	char gridFileName[1024];
	err=ReadBjnGzippedScalar8RecInfo( s, bjn_info);
	if(err) return err;
	/*PrnBjnInfo(stdout, bjn_info);*/
	getGridName(s, bjn_info->gridname, gridFileName);
	err=ReadBjnGzippedScalar8RecFunc( gridFileName, "x", &(p1->x), &(p1->MAXi), &(p1->MAXj), &(p1->MAXk) );
	if(err) return err;
	err=ReadBjnGzippedScalar8RecFunc( gridFileName, "y", &(p1->y), &(p1->MAXi), &(p1->MAXj), &(p1->MAXk) );
	if(err) return err;
	err=ReadBjnGzippedScalar8RecFunc( gridFileName, "z", &(p1->z), &(p1->MAXi), &(p1->MAXj), &(p1->MAXk) );
	if(err) return err;
	err=ReadBjnGzippedScalar8RecFunc( s, f, &(p1->f), &(p1->MAXi), &(p1->MAXj), &(p1->MAXk) );
	if(err) return err;	
/*	printf(gridFileName);printf("\n");*/
/* 
	for(j=0; j< p1->MAXj; j++)
		for(k=0; k< p1->MAXk; k++)
		{
		float fmin=0.;
		float fmax=p1->MAXj+p1->MAXk-2;

	(p1->f)[0][j][k]=0.;
	(p1->f)[1][j][k]=
		
		1.5 / ( 1.+ ( (j+k) - fmin ) / ( fmax - fmin)   )

		;
		}
*/
#endif
  return 0;
}

/**
 * E`ta procedura inicializiruet oc`eredx(ste`k FIFO)
 */
void initStackFIFO(BigFilePointer *p1)
{
   /* allocate memory for main pool */
   if ((p1->head = (struct node *) malloc( sizeof(struct node) )) == NULL)
   {
      printf("Not enough memory to allocate buffer\n");
      exit(1);  /* terminate program if out of memory */
   }

   /* allocate memory for poli pool */
   if ((p1->poli_head = (struct poli_pool *) malloc( sizeof(struct poli_pool) )) == NULL)
   {
      printf("Not enough memory to allocate buffer\n");
      exit(1);  /* terminate program if out of memory */
   }

   p1->filledSize=0;
   p1->temp2=p1->head;
   p1->stackSize=1;

   p1->poli_filledSize=0;
   p1->poli_temp2=p1->poli_head;
   p1->poli_stackSize=1;
   p1->cBoundaryPlots = 0;
   /*printf("stack init OK\n");*/
   return;
}

/**
 * Procedura "klady`t" toc`ku(x, y, z - koordinaty toc`ki i nomer rebra)
 * v oc`eredx
 */
void put(BigFilePointer *p1, float xl, float yl, float zl, int lo, bool b)
{
//	printf("PUT\n");
//   int i;
/***********
   int bNew;

   bNew = 1;
   if (n_temp > 0)
   {
      for( i = 0 ; i < n_temp ; i++ )
      {
         if( (xl==x_temp[i]) && (yl==y_temp[i]) && (zl==z_temp[i]) )
         {
             bNew = 0;
             
             links[0][n_temp] = lo ;
             links[1][n_temp] = l_temp[i] ;
             
             break;
         }
      }
   }

   if(bNew == 1)
   {
************/
       if (p1->filledSize == Number )
       {
          if ((p1->temp = (struct node *) malloc( sizeof(struct node) )) == NULL)
          {
             printf("Not enough memory to allocate buffer\n");
             exit(1);  
          }
          p1->temp2->p   = p1->temp;
          p1->temp2      = p1->temp;
          p1->stackSize++; 
          p1->filledSize=0;
       } 
/* 010427_18.50       p1->temp2->l[p1->filledSize]=lo;*/
       p1->temp2->x[p1->filledSize]=xl;
       p1->temp2->y[p1->filledSize]=yl;
       p1->temp2->z[p1->filledSize]=zl;
       p1->temp2->b[p1->filledSize]=b;
       p1->filledSize++;
       p1->plots[p1->plots_number++]=lo;

	   if(b)
		   p1->cBoundaryPlots++;
	   // boundary 050814 18:54
//	   if(b)
//		   p1->plots.boundary[p1->plots.plots_number-1] = true;
//	   else
//		   p1->plots.boundary[p1->plots.plots_number-1] = false;

/****************
       x_temp[n_temp]=xl;
       y_temp[n_temp]=yl;
       z_temp[n_temp]=zl;
       l_temp[n_temp]=lo;
       n_temp++;
       if(n_temp>49) printf("n_temp>49\n");

    }
********************/

/*
    printf("n_temp=%d stackSize=%d filledSize=%d lo=%d\n",n_temp,p1->stackSize, p1->filledSize, lo);
*/
    /*remember_plot(p1,lo);*/
   return;
}

void addPoli(BigFilePointer *p1, int n1, int n2, int n3)
{

   if (p1->poli_filledSize >= POLI_SIZE )
   {
      if ((p1->poli_temp = (struct poli_pool *) malloc( sizeof(struct poli_pool) )) == NULL)
      {
         printf("Not enough memory to allocate buffer\n");
         exit(1);
      }
      p1->poli_temp2->p   = p1->poli_temp;
      p1->poli_temp2      = p1->poli_temp;
      p1->poli_stackSize++;
      p1->poli_filledSize=0;
   }
   p1->poli_temp2->pool[p1->poli_filledSize]=n1;
   p1->poli_filledSize++;
   p1->poli_temp2->pool[p1->poli_filledSize]=n2;
   p1->poli_filledSize++;
   p1->poli_temp2->pool[p1->poli_filledSize]=n3;
   p1->poli_filledSize++;

   return;
}

/**
 * Osvobojdenie zana`toi` pod oc`eredx pama`ti
 */
void freeMemory(BigFilePointer *p1)
{
int i_temp;
 /* FREENG MAIN POOL*/
   for(i_temp=1 ; i_temp < p1->stackSize ; i_temp++ )
   {
      p1->temp = p1->head->p;
      free(p1->head); p1->head = NULL;
      p1->head = p1->temp;
   }

   free(p1->head); p1->head = NULL;
   p1->stackSize  = 0;
   p1->filledSize = 0;

 /* FREENG POLI POOL*/
   for(i_temp=1 ; i_temp < p1->poli_stackSize ; i_temp++ )
   {
      p1->poli_temp = p1->poli_head->p;
      free(p1->poli_head); p1->poli_head = NULL;
      p1->poli_head = p1->poli_temp;
   }

   free(p1->poli_head); p1->poli_head = NULL;
   p1->poli_stackSize  = 0;
   p1->poli_filledSize = 0;

   return;
}

/**
 * Dannaa` procedura sodarjit osnovnoi` cikl obhoda uzlov i
 * poisk iskomyh toc`ek - bez opredelenia` vhojdenii` toc`ki
 * poligonam.
 * - Value      - velic`ina funkcii iskomoi` poverhnosti urovna`
 * - returnHead - ssylka na linei`nyi` spisok poluc`ennyh toc`ek
 */
void docount2_inner(BigFilePointer *p1, float Value, int cMethod, float cParams, int cRealBounds)
{
    int i, j, k;
//    int iii;
	bool 
		b_ijk=false,
		b_i1jk=false,
		b_ij1k=false,
		b_ijk1=false,
		b_i1j1k=false,
		b_i1jk1=false,
		b_ij1k1=false,
		b_i1j1k1=false;

	unsigned long t1, t2;//, t3, t4;

#ifndef KP_UNIX
t1=timeGetTime();
#endif
//printf("time %lu\n", t3);

    p1->bias = 0;
    initStackFIFO(p1);
    /*printf("in docount %d %d %d and %f %f\n",
    	p1->MAXi, p1->MAXj, p1->MAXk, Value,
    	p1->f[p1->MAXi-1][p1->MAXj-1][p1->MAXk-1]);
    	*/
    for(i=0; i<(p1->MAXi-1); i++)
    {
    for(j=0; j<(p1->MAXj-1); j++)
    for(k=0; k<(p1->MAXk-1); k++)
        {   /* uslovie prohojdenia` poverhnosti c`erez kub */
        	/*printf("..int for for for \n");*/
            /*printf("...before if...%d %d %d %f\n", i, j, k, p1->f[i][j][k]);*/
            if(!(((p1->f[i][j][k]    > Value)&&
                (p1->f[i+1][j][k]    > Value)&&
                (p1->f[i][j+1][k]    > Value)&&
                (p1->f[i][j][k+1]    > Value)&&
                (p1->f[i+1][j+1][k]  > Value)&&
                (p1->f[i+1][j][k+1]  > Value)&&
                (p1->f[i][j+1][k+1]  > Value)&&
                (p1->f[i+1][j+1][k+1]> Value))||
                ((p1->f[i][j][k]     < Value)&&
                (p1->f[i+1][j][k]    < Value)&&
                (p1->f[i][j+1][k]    < Value)&&
                (p1->f[i][j][k+1]    < Value)&&
                (p1->f[i+1][j+1][k]  < Value)&&
                (p1->f[i+1][j][k+1]  < Value)&&
                (p1->f[i][j+1][k+1]  < Value)&&
                (p1->f[i+1][j+1][k+1]< Value)))) {
            p1->plots_number = 0;
//			p1->boundary_plots_number = 0;

		// mark boundary points 
			b_ijk=false;
			b_i1jk=false;
			b_ij1k=false;
			b_ijk1=false;
			b_i1j1k=false;
			b_i1jk1=false;
			b_ij1k1=false;
			b_i1j1k1=false;
			if (0 == i) 
				if( !(X_MIN_BOUND & cRealBounds) )
					{b_ijk=b_ij1k=b_ijk1=b_ij1k1=true;} 
			if (0 == j) 
				if( !(Y_MIN_BOUND & cRealBounds) )
					{b_ijk=b_i1jk=b_ijk1=b_i1jk1=true;} 
			if (0 == k)
				if( !(Z_MIN_BOUND & cRealBounds) )
					{b_ijk=b_i1jk=b_ij1k=b_i1j1k=true;} 
			if ((p1->MAXi-2)==i) 
				if( !(X_MAX_BOUND & cRealBounds) )
					{b_i1jk=b_i1j1k=b_i1jk1=b_i1j1k1=true;} 
			if ((p1->MAXj-2)==j)
				if( !(Y_MAX_BOUND & cRealBounds) )
					{b_ij1k=b_i1j1k=b_ij1k1=b_i1j1k1=true;} 
			if ((p1->MAXk-2)==k) 
				if( !(Z_MAX_BOUND & cRealBounds) )
					{b_ijk1=b_i1jk1=b_ij1k1=b_i1j1k1=true;} 

			
//			if(!(b_ijk&&b_i1jk&&b_ij1k&&b_ijk1&&b_i1j1k&&b_i1jk1&&b_ij1k1&&b_i1j1k1))
//				printf("error %d %d %d %d %d %d %d %d %d %d %d\n", 
//					i, j, k,
//					b_ijk, b_ij1k, b_ij1k1, b_ijk1,
//					b_i1jk, b_i1j1k, b_i1j1k1, b_i1jk1);

           /* printf("...in if...%d %d %d %f\n", i, j, k, p1->f[i][j][k]);*/
           countCub2(p1->f[i  ][j  ][k  ],p1->x[i  ][j  ][k  ],p1->y[i  ][j  ][k  ],p1->z[i  ][j  ][k  ], b_ijk,
                     p1->f[i+1][j  ][k  ],p1->x[i+1][j  ][k  ],p1->y[i+1][j  ][k  ],p1->z[i+1][j  ][k  ], b_i1jk,
                     p1->f[i  ][j+1][k  ],p1->x[i  ][j+1][k  ],p1->y[i  ][j+1][k  ],p1->z[i  ][j+1][k  ], b_ij1k,
                     p1->f[i  ][j  ][k+1],p1->x[i  ][j  ][k+1],p1->y[i  ][j  ][k+1],p1->z[i  ][j  ][k+1], b_ijk1,
                     p1->f[i+1][j+1][k  ],p1->x[i+1][j+1][k  ],p1->y[i+1][j+1][k  ],p1->z[i+1][j+1][k  ], b_i1j1k,
                     p1->f[i+1][j  ][k+1],p1->x[i+1][j  ][k+1],p1->y[i+1][j  ][k+1],p1->z[i+1][j  ][k+1], b_i1jk1,
                     p1->f[i  ][j+1][k+1],p1->x[i  ][j+1][k+1],p1->y[i  ][j+1][k+1],p1->z[i  ][j+1][k+1], b_ij1k1,
                     p1->f[i+1][j+1][k+1],p1->x[i+1][j+1][k+1],p1->y[i+1][j+1][k+1],p1->z[i+1][j+1][k+1], b_i1j1k1,
                     Value, i, j, k, p1);
            /*create_topology(i,j,k,bias,p1);*/
/*            if(p1->stackSize>MAXSS)
            {
                sendAll(msgsock, p1);
                initStackFIFO(p1);
            }
*/
            }  else
            {
/*            	fprintf(stderr, "kp97_err: %d %d %d %d %d %d | %f %f %f %f | %f %f %f %f\n",
            	i, j, k, p1->MAXi, p1->MAXj, p1->MAXk,
                p1->f[i][j][k], p1->f[i+1][j][k],
                p1->f[i][j+1][k], p1->f[i][j][k+1], 
                p1->f[i+1][j+1][k], p1->f[i+1][j][k+1],
                p1->f[i][j+1][k+1], p1->f[i+1][j+1][k+1]
            	);
*/
            }
        }
    }
#ifndef KP_UNIX
t2=timeGetTime();
#endif
    if((p1->filledSize!=0)||(p1->stackSize >1))
    {
        sendAll2_inner(p1, cMethod, cParams);
    }
    else
    {
	    stopSending_inner();
    	freeMemory(p1);
	}
#ifndef KP_UNIX
//printf("_docount2_time %lu\n", t2-t1);
#endif
    return;
}


void docount3_inner(BigFilePointer *p1, float Value, int cMethod, float cParams, float *memFloat, int cRealBounds)
{
    int i, j, k;
//    int iii;
	bool 
		b_ijk=false,
		b_i1jk=false,
		b_ij1k=false,
		b_ijk1=false,
		b_i1j1k=false,
		b_i1jk1=false,
		b_ij1k1=false,
		b_i1j1k1=false;

	printf("docount3\n");
    p1->bias = 0;
    initStackFIFO(p1);
    for(i=0; i<(p1->MAXi-1); i++)
    {
    for(j=0; j<(p1->MAXj-1); j++)
    for(k=0; k<(p1->MAXk-1); k++)
        {   /* uslovie prohojdenia` poverhnosti c`erez kub */
        	/*printf("..int for for for \n");*/
            if((!((p1->x[i][j][k]>memFloat[0])||(p1->x[i+1][j+1][k+1]<memFloat[1]))
              &&!((p1->y[i][j][k]>memFloat[2])||(p1->y[i+1][j+1][k+1]<memFloat[3]))
              &&!((p1->z[i][j][k]>memFloat[4])||(p1->z[i+1][j+1][k+1]<memFloat[5]))  )
				&&(!(((p1->f[i][j][k]    > Value)&&
                (p1->f[i+1][j][k]    > Value)&&
                (p1->f[i][j+1][k]    > Value)&&
                (p1->f[i][j][k+1]    > Value)&&
                (p1->f[i+1][j+1][k]  > Value)&&
                (p1->f[i+1][j][k+1]  > Value)&&
                (p1->f[i][j+1][k+1]  > Value)&&
                (p1->f[i+1][j+1][k+1]> Value))||
                ((p1->f[i][j][k]     < Value)&&
                (p1->f[i+1][j][k]    < Value)&&
                (p1->f[i][j+1][k]    < Value)&&
                (p1->f[i][j][k+1]    < Value)&&
                (p1->f[i+1][j+1][k]  < Value)&&
                (p1->f[i+1][j][k+1]  < Value)&&
                (p1->f[i][j+1][k+1]  < Value)&&
                (p1->f[i+1][j+1][k+1]< Value)))) ) {
            p1->plots_number = 0;
//			p1->boundary_plots_number = 0;

		// mark boundary points 
			b_ijk=false;
			b_i1jk=false;
			b_ij1k=false;
			b_ijk1=false;
			b_i1j1k=false;
			b_i1jk1=false;
			b_ij1k1=false;
			b_i1j1k1=false;
			if (0 == i) 
				if( !(X_MIN_BOUND & cRealBounds) )
					{b_ijk=b_ij1k=b_ijk1=b_ij1k1=true;} 
			if (0 == j) 
				if( !(Y_MIN_BOUND & cRealBounds) )
					{b_ijk=b_i1jk=b_ijk1=b_i1jk1=true;} 
			if (0 == k)
				if( !(Z_MIN_BOUND & cRealBounds) )
					{b_ijk=b_i1jk=b_ij1k=b_i1j1k=true;} 
			if ((p1->MAXi-2)==i) 
				if( !(X_MAX_BOUND & cRealBounds) )
					{b_i1jk=b_i1j1k=b_i1jk1=b_i1j1k1=true;} 
			if ((p1->MAXj-2)==j)
				if( !(Y_MAX_BOUND & cRealBounds) )
					{b_ij1k=b_i1j1k=b_ij1k1=b_i1j1k1=true;} 
			if ((p1->MAXk-2)==k) 
				if( !(Z_MAX_BOUND & cRealBounds) )
					{b_ijk1=b_i1jk1=b_ij1k1=b_i1j1k1=true;} 

            /*printf("...in if...\n");*/
           countCub2(p1->f[i  ][j  ][k  ],p1->x[i  ][j  ][k  ],p1->y[i  ][j  ][k  ],p1->z[i  ][j  ][k  ], b_ijk,
                     p1->f[i+1][j  ][k  ],p1->x[i+1][j  ][k  ],p1->y[i+1][j  ][k  ],p1->z[i+1][j  ][k  ], b_i1jk,
                     p1->f[i  ][j+1][k  ],p1->x[i  ][j+1][k  ],p1->y[i  ][j+1][k  ],p1->z[i  ][j+1][k  ], b_ij1k,
                     p1->f[i  ][j  ][k+1],p1->x[i  ][j  ][k+1],p1->y[i  ][j  ][k+1],p1->z[i  ][j  ][k+1], b_ijk1,
                     p1->f[i+1][j+1][k  ],p1->x[i+1][j+1][k  ],p1->y[i+1][j+1][k  ],p1->z[i+1][j+1][k  ], b_i1j1k,
                     p1->f[i+1][j  ][k+1],p1->x[i+1][j  ][k+1],p1->y[i+1][j  ][k+1],p1->z[i+1][j  ][k+1], b_i1jk1,
                     p1->f[i  ][j+1][k+1],p1->x[i  ][j+1][k+1],p1->y[i  ][j+1][k+1],p1->z[i  ][j+1][k+1], b_ij1k1,
                     p1->f[i+1][j+1][k+1],p1->x[i+1][j+1][k+1],p1->y[i+1][j+1][k+1],p1->z[i+1][j+1][k+1], b_i1j1k1,
                     Value, i, j, k, p1);
            /*create_topology(i,j,k,bias,p1);*/
/*
            if(p1->stackSize>MAXSS)
            {
                sendAll(msgsock, p1);
                initStackFIFO(p1);
            }
*/
            }
        }
    }
    /*printf("docount finished with grid\n");*/
    if((p1->filledSize!=0)||(p1->stackSize >1))
    {
        /*printf("starting after docount sendAll\n");*/
        sendAll2_inner(p1, cMethod, cParams);
    }
    else
    {
	    stopSending_inner();
    	freeMemory(p1);
    }
    return;
}

void docountZOOMgdc(BigFilePointer *p1, float Value, int cMethod, float cParams, float *memFloat)
{
    int i;

	printf("docountZOOMgdc\n");
    p1->bias = 0;
    initStackFIFO(p1);
    for(i=0; i<(p1->MAXi-1); i++)
    {
            if((!((p1->pCoords[p1->pTetr[i*4+0]*3+0]>memFloat[0])||(p1->pCoords[p1->pTetr[i*4+3]*3+0]<memFloat[1]))
              &&!((p1->pCoords[p1->pTetr[i*4+0]*3+1]>memFloat[2])||(p1->pCoords[p1->pTetr[i*4+3]*3+1]<memFloat[3]))
              &&!((p1->pCoords[p1->pTetr[i*4+0]*3+2]>memFloat[4])||(p1->pCoords[p1->pTetr[i*4+3]*3+2]<memFloat[5]))  )
/*TODO				&&(!(((p1->f[i][j][k]    > Value)&&
                (p1->f[i+1][j][k]    > Value)&&
                (p1->f[i][j+1][k]    > Value)&&
                (p1->f[i][j][k+1]    > Value)&&
                (p1->f[i+1][j+1][k]  > Value)&&
                (p1->f[i+1][j][k+1]  > Value)&&
                (p1->f[i][j+1][k+1]  > Value)&&
                (p1->f[i+1][j+1][k+1]> Value))||
                ((p1->f[i][j][k]     < Value)&&
                (p1->f[i+1][j][k]    < Value)&&
                (p1->f[i][j+1][k]    < Value)&&
                (p1->f[i][j][k+1]    < Value)&&
                (p1->f[i+1][j+1][k]  < Value)&&
                (p1->f[i+1][j][k+1]  < Value)&&
                (p1->f[i][j+1][k+1]  < Value)&&
                (p1->f[i+1][j+1][k+1]< Value)))) 
*/				) {
		// TODO
        p1->plots_number = 0;
		countTETRA(
			(float)p1->pCoords[p1->pTetr[i*4+0]*3], (float)p1->pCoords[p1->pTetr[i*4+0]*3+1], (float)p1->pCoords[p1->pTetr[i*4+0]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+1]*3], (float)p1->pCoords[p1->pTetr[i*4+1]*3+1], (float)p1->pCoords[p1->pTetr[i*4+1]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+2]*3], (float)p1->pCoords[p1->pTetr[i*4+2]*3+1], (float)p1->pCoords[p1->pTetr[i*4+2]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+3]*3], (float)p1->pCoords[p1->pTetr[i*4+3]*3+1], (float)p1->pCoords[p1->pTetr[i*4+3]*3+2], 
			(float)p1->pFunc[p1->pTetr[i*4+0]], (float)p1->pFunc[p1->pTetr[i*4+1]],
			(float)p1->pFunc[p1->pTetr[i*4+2]], (float)p1->pFunc[p1->pTetr[i*4+3]],
            Value, i, p1);			
			
			}
    }
    /*printf("docount finished with grid\n");*/
    if((p1->filledSize!=0)||(p1->stackSize >1))
    {
        sendAll2_inner(p1, cMethod, cParams);
    }
    else
    {
	    stopSending_inner();
    	freeMemory(p1);
    }
    return;
}

void docountGDC(BigFilePointer *p1, float Value, int cMethod, float cParams)
{
    int i;
//    int iii;

	unsigned long t1, t2;//, t3, t4;

#ifndef KP_UNIX
t1=timeGetTime();
#endif
// BUGBUGBUG
//p1->MAXi = p1->nTetra+1;
//printf("docountGDC %d %d\n", p1->MAXi, p1->nTetra);
    p1->bias = 0;
    initStackFIFO(p1);
    for(i=0; i<(p1->MAXi-1); i++)
    {
		//TODO
        p1->plots_number = 0;
		countTETRA(
			(float)p1->pCoords[p1->pTetr[i*4+0]*3], (float)p1->pCoords[p1->pTetr[i*4+0]*3+1], (float)p1->pCoords[p1->pTetr[i*4+0]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+1]*3], (float)p1->pCoords[p1->pTetr[i*4+1]*3+1], (float)p1->pCoords[p1->pTetr[i*4+1]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+2]*3], (float)p1->pCoords[p1->pTetr[i*4+2]*3+1], (float)p1->pCoords[p1->pTetr[i*4+2]*3+2], 
			(float)p1->pCoords[p1->pTetr[i*4+3]*3], (float)p1->pCoords[p1->pTetr[i*4+3]*3+1], (float)p1->pCoords[p1->pTetr[i*4+3]*3+2], 
			(float)p1->pFunc[p1->pTetr[i*4+0]], (float)p1->pFunc[p1->pTetr[i*4+1]],
			(float)p1->pFunc[p1->pTetr[i*4+2]], (float)p1->pFunc[p1->pTetr[i*4+3]],
            Value, i, p1);			
    }
#ifndef KP_UNIX
t2=timeGetTime();
#endif
//printf("rez = %d %d\n", p1->filledSize, p1->stackSize);
    if((p1->filledSize!=0)||(p1->stackSize >1))
    {
        sendAll2_inner(p1, cMethod, cParams);
    }
    else
    {
	    stopSending_inner();
    	freeMemory(p1);
	}
#ifdef KP_UNIX
//printf("_docountGDC_time %lu\n", t2-t1);
#endif
    return;
}


void create_topologyTETRA(int i, BigFilePointer *p1)
{         
	int nplots[12];
	int number_of_nplots;
	number_of_nplots = 0;
	int ii, i_;

	for( ii = 0 ; ii < p1->plots_number ; ++ii )
	{
		nplots[number_of_nplots++] = 1+ii+p1->bias;
	}

    switch (number_of_nplots) 
    {
		case 3:
			addPoli( p1 , nplots[0], nplots[1], nplots[2]);
            break;
            
        case  4:
        case  5:
        case  6:
        case  7:
        case  8:
        case  9:
        case 10:
        case 11:
        case 12:
			for(i_=1; i_<number_of_nplots-1;i_++)
            {
				addPoli(p1, nplots[0], nplots[i_], nplots[i_+1]);
            }
			break;
              
        case 2:
            addPoli(p1, nplots[0], nplots[1], nplots[0]);
            break;

		default:
			break;

    }

    p1->bias += p1->plots_number;
    return;
}


int countTETRANumber(int i, int edgeNumber, BigFilePointer *p1)
{
	return (6*i + edgeNumber);
}

void countTETRA(
			float x1, float y1, float z1, 
			float x2, float y2, float z2, 
			float x3, float y3, float z3, 
			float x4, float y4, float z4, 
			float f1, float f2, float f3, float f4, 
            float Value, int i, BigFilePointer *p1)
{
	// ToDo ADD BOUNDARY PARAMETERS HERE!!!!!
    countSide2(f1, f2, x1, x2, y1, y2, z1, z2, Value, countTETRANumber(i, 0, p1), p1, 1, 1, false, false);
    countSide2(f2, f3, x2, x3, y2, y3, z2, z3, Value, countTETRANumber(i, 1, p1), p1, 0, 1, false, false);
    countSide2(f3, f1, x3, x1, y3, y1, z3, z1, Value, countTETRANumber(i, 2, p1), p1, 0, 0, false, false);

    countSide2(f4, f3, x4, x3, y4, y3, z4, z3, Value, countTETRANumber(i, 3, p1), p1, 0, 0, false, false);
    countSide2(f1, f4, x1, x4, y1, y4, z1, z4, Value, countTETRANumber(i, 4, p1), p1, 0, 1, false, false);
    countSide2(f2, f4, x2, x4, y2, y4, z2, z4, Value, countTETRANumber(i, 5, p1), p1, 0, 0, false, false);
	//printf("%e\n%e\n%e\n%e\n");
	create_topologyTETRA(i,p1);
}			



/**
 * Rasc`y`t otdelxnogo kuba(6-ti grannoi` figury)
 * zdesx proizvoditsa` vyc`islenia` opornyh toc`ek
 * delenie "kuba" na grani i opredelenie teh
 * granei`, kotorye nujno "obsc`ityvatx" 
 */
void countCub(float fa, float xa, float ya, float za, 
              float fb, float xb, float yb, float zb, 
              float fd, float xd, float yd, float zd, 
              float fe, float xe, float ye, float ze, 
              float fc, float xc, float yc, float zc, 
              float ff, float xf, float yf, float zf, 
              float fh, float xh, float yh, float zh, 
              float fg, float xg, float yg, float zg, 
              float Value, int i, int j, int k, BigFilePointer *p1)
{
/*****TEMP**/
//   int j1;
/***********/
    /* vyc`isla`em znac`enie funkcii v 7mi opornyh toc`kah */
    float f1,f2,f3,f4,f5,f6,f7;
    float x1,x2,x3,x4,x5,x6,x7;
    float y1,y2,y3,y4,y5,y6,y7;
    float z1,z2,z3,z4,z5,z6,z7;

    f2=(fa+fb+fc+fd)/4.0f;
    f3=(fe+ff+fg+fh)/4.0f;
    f4=(fa+fd+fh+fe)/4.0f;
    f5=(fb+fc+fg+ff)/4.0f;
    f6=(fa+fb+ff+fe)/4.0f;
    f7=(fd+fc+fg+fh)/4.0f;
    f1=(f2+f3+f4+f5+f6+f7)/6.0f;

    x2=(xa+xb+xc+xd)/4.0f;
    x3=(xe+xf+xg+xh)/4.0f;
    x4=(xa+xd+xh+xe)/4.0f;
    x5=(xb+xc+xg+xf)/4.0f;
    x6=(xa+xb+xf+xe)/4.0f;
    x7=(xd+xc+xg+xh)/4.0f;
    x1=(x2+x3+x4+x5+x6+x7)/6.0f;

    y2=(ya+yb+yc+yd)/4.0f;
    y3=(ye+yf+yg+yh)/4.0f;
    y4=(ya+yd+yh+ye)/4.0f;
    y5=(yb+yc+yg+yf)/4.0f;
    y6=(ya+yb+yf+ye)/4.0f;
    y7=(yd+yc+yg+yh)/4.0f;
    y1=(y2+y3+y4+y5+y6+y7)/6.0f;

    z2=(za+zb+zc+zd)/4.0f;
    z3=(ze+zf+zg+zh)/4.0f;
    z4=(za+zd+zh+ze)/4.0f;
    z5=(zb+zc+zg+zf)/4.0f;
    z6=(za+zb+zf+ze)/4.0f;
    z7=(zd+zc+zg+zh)/4.0f;
    z1=(z2+z3+z4+z5+z6+z7)/6.0f;

/*_________DECREASE PLOTS NUMBER_________--*/
/********************8   n_temp = 0 ;****************/
   /*for(j1=0;j1<100;j1++) links[j1]=0;*/
   /*memset(&l_temp, 0, sizeof(l_temp));*/

/*_________DECREASE PLOTS NUMBER_________--*/

    /** rasc`y`t 14ti vnutrennih ry`ber i 15ti ry`ber na grana`h -
       - obsc`ityvaemye vsegda (dla` vseh kubov)*/
    /* vnutrennie ry`bra (14) */
    /* a1 b1 c1 d1 e1 f1 g1 h1 21 61 31 71 51 41 */
    /* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 */
    countSide(fa, f1, xa, x1, ya, y1, za, z1, Value, countCubNumber(i, j, k,  0, p1), p1);
    countSide(fb, f1, xb, x1, yb, y1, zb, z1, Value, countCubNumber(i, j, k,  1, p1), p1);
    countSide(fc, f1, xc, x1, yc, y1, zc, z1, Value, countCubNumber(i, j, k,  2, p1), p1);
    countSide(fd, f1, xd, x1, yd, y1, zd, z1, Value, countCubNumber(i, j, k,  3, p1), p1);
    countSide(fe, f1, xe, x1, ye, y1, ze, z1, Value, countCubNumber(i, j, k,  4, p1), p1);
    countSide(ff, f1, xf, x1, yf, y1, zf, z1, Value, countCubNumber(i, j, k,  5, p1), p1);
    countSide(fg, f1, xg, x1, yg, y1, zg, z1, Value, countCubNumber(i, j, k,  6, p1), p1);
    countSide(fh, f1, xh, x1, yh, y1, zh, z1, Value, countCubNumber(i, j, k,  7, p1), p1);
    countSide(f2, f1, x2, x1, y2, y1, z2, z1, Value, countCubNumber(i, j, k,  8, p1), p1);
    countSide(f6, f1, x6, x1, y6, y1, z6, z1, Value, countCubNumber(i, j, k,  9, p1), p1);
    countSide(f3, f1, x3, x1, y3, y1, z3, z1, Value, countCubNumber(i, j, k, 10, p1), p1);
    countSide(f7, f1, x7, x1, y7, y1, z7, z1, Value, countCubNumber(i, j, k, 11, p1), p1);
    countSide(f5, f1, x5, x1, y5, y1, z5, z1, Value, countCubNumber(i, j, k, 12, p1), p1);
    countSide(f4, f1, x4, x1, y4, y1, z4, z1, Value, countCubNumber(i, j, k, 13, p1), p1);
                                                                                
    /* ry`bra na grana`h (15) */
    /* b5 c5 f5 g5 e3 f3 g3 h3 d7 c7 g7 h7 gc gf gh*/
    /* 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28*/
    countSide(fb, f5, xb, x5, yb, y5, zb, z5, Value, countCubNumber(i, j, k, 14, p1), p1);
    countSide(fc, f5, xc, x5, yc, y5, zc, z5, Value, countCubNumber(i, j, k, 15, p1), p1);
    countSide(ff, f5, xf, x5, yf, y5, zf, z5, Value, countCubNumber(i, j, k, 16, p1), p1);
    countSide(fg, f5, xg, x5, yg, y5, zg, z5, Value, countCubNumber(i, j, k, 17, p1), p1);
    countSide(fe, f3, xe, x3, ye, y3, ze, z3, Value, countCubNumber(i, j, k, 18, p1), p1);
    countSide(ff, f3, xf, x3, yf, y3, zf, z3, Value, countCubNumber(i, j, k, 19, p1), p1);
    countSide(fg, f3, xg, x3, yg, y3, zg, z3, Value, countCubNumber(i, j, k, 20, p1), p1);
    countSide(fh, f3, xh, x3, yh, y3, zh, z3, Value, countCubNumber(i, j, k, 21, p1), p1);
    countSide(fd, f7, xd, x7, yd, y7, zd, z7, Value, countCubNumber(i, j, k, 22, p1), p1);
    countSide(fc, f7, xc, x7, yc, y7, zc, z7, Value, countCubNumber(i, j, k, 23, p1), p1);
    countSide(fg, f7, xg, x7, yg, y7, zg, z7, Value, countCubNumber(i, j, k, 24, p1), p1);
    countSide(fh, f7, xh, x7, yh, y7, zh, z7, Value, countCubNumber(i, j, k, 25, p1), p1);
    countSide(fg, fc, xg, xc, yg, yc, zg, zc, Value, countCubNumber(i, j, k, 26, p1), p1);
    countSide(fg, ff, xg, xf, yg, yf, zg, zf, Value, countCubNumber(i, j, k, 27, p1), p1);
    countSide(fg, fh, xg, xh, yg, yh, zg, zh, Value, countCubNumber(i, j, k, 28, p1), p1);

    /** rasc`y`t 6ti ry`ber na grani xy=ij(k=l)*/
    /* a2 b2 c2 d2 bc cd */
    /* 29 30 31 32 33 34 */
/*    if(k==0)
 *   {
 */
        countSide(fa, f2, xa, x2, ya, y2, za, z2, Value, countCubNumber(i, j, k, 29, p1), p1);
        countSide(fb, f2, xb, x2, yb, y2, zb, z2, Value, countCubNumber(i, j, k, 30, p1), p1);
        countSide(fc, f2, xc, x2, yc, y2, zc, z2, Value, countCubNumber(i, j, k, 31, p1), p1);
        countSide(fd, f2, xd, x2, yd, y2, zd, z2, Value, countCubNumber(i, j, k, 32, p1), p1);
        countSide(fb, fc, xb, xc, yb, yc, zb, zc, Value, countCubNumber(i, j, k, 33, p1), p1);
        countSide(fc, fd, xc, xd, yc, yd, zc, zd, Value, countCubNumber(i, j, k, 34, p1), p1);
/*   }
 */
    /** rasc`y`t 6ti ry`ber na grani xz=ik(j=m)*/
    /* a6 b6 f6 e6 bf fe */
    /* 35 36 37 38 39 40 */
/*    if(j==0)
 *   {
 */
        countSide(fa, f6, xa, x6, ya, y6, za, z6, Value, countCubNumber(i, j, k, 35, p1), p1);
        countSide(fb, f6, xb, x6, yb, y6, zb, z6, Value, countCubNumber(i, j, k, 36, p1), p1);
        countSide(ff, f6, xf, x6, yf, y6, zf, z6, Value, countCubNumber(i, j, k, 37, p1), p1);
        countSide(fe, f6, xe, x6, ye, y6, ze, z6, Value, countCubNumber(i, j, k, 38, p1), p1);
        countSide(fb, ff, xb, xf, yb, yf, zb, zf, Value, countCubNumber(i, j, k, 39, p1), p1);
        countSide(ff, fe, xf, xe, yf, ye, zf, ze, Value, countCubNumber(i, j, k, 40, p1), p1);
/*    }
 */

    /** rasc`y`t 6ti ry`ber na grani yz=jk(i=n)*/
    /* a4 d4 h4 e4 dh he */
    /* 41 42 43 44 45 46 */
/*    if(i==0)
 *   {
 */
        countSide(fa, f4, xa, x4, ya, y4, za, z4, Value, countCubNumber(i, j, k, 41, p1), p1);
        countSide(fd, f4, xd, x4, yd, y4, zd, z4, Value, countCubNumber(i, j, k, 42, p1), p1);
        countSide(fh, f4, xh, x4, yh, y4, zh, z4, Value, countCubNumber(i, j, k, 43, p1), p1);
        countSide(fe, f4, xe, x4, ye, y4, ze, z4, Value, countCubNumber(i, j, k, 44, p1), p1);
        countSide(fd, fh, xd, xh, yd, yh, zd, zh, Value, countCubNumber(i, j, k, 45, p1), p1);
        countSide(fh, fe, xh, xe, yh, ye, zh, ze, Value, countCubNumber(i, j, k, 46, p1), p1);
/*    }
 */

    /** rasc`y`t ry`bera         ab =Ox(k=l,j=m) */
    /*                        47             */
/*    if((k==0)&&(j==0))*/
        countSide(fa, fb, xa, xb, ya, yb, za, zb, Value, countCubNumber(i, j, k, 47, p1), p1);

    /** rasc`y`t ry`bera         ad =Oy(k=l,i=n) */
    /*                        48             */
/*    if((k==0)&&(i==0))*/
        countSide(fa, fd, xa, xd, ya, yd, za, zd, Value, countCubNumber(i, j, k, 48, p1), p1);

    /** rasc`y`t ry`bera         ae =Oz(j=m,i=n) */
    /*                        49             */
/*    if((j==0)&&(i==0))*/
        countSide(fa, fe, xa, xe, ya, ye, za, ze, Value, countCubNumber(i, j, k, 49, p1), p1);

   decreasePlotsNumber();
   create_topology(i,j,k,p1);
   return;
};                 

/**
 * Rasc`y`t otdelxnogo kuba(6-ti grannoi` figury)
 * zdesx proizvoditsa` vyc`islenia` opornyh toc`ek
 * delenie "kuba" na grani i opredelenie teh
 * granei`, kotorye nujno "obsc`ityvatx"
 */
void countCub2(float fa, float xa, float ya, float za, bool ba,
              float fb, float xb, float yb, float zb, bool bb,
              float fd, float xd, float yd, float zd, bool bd,
              float fe, float xe, float ye, float ze, bool be,
              float fc, float xc, float yc, float zc, bool bc,
              float ff, float xf, float yf, float zf, bool bf,
              float fh, float xh, float yh, float zh, bool bh,
              float fg, float xg, float yg, float zg, bool bg,
              float Value, int i, int j, int k, BigFilePointer *p1)
{
/*****TEMP**/
//   int j1;
/***********/

/*_________DECREASE PLOTS NUMBER_________--*/
/********************8   n_temp = 0 ;****************/
   /*for(j1=0;j1<100;j1++) links[j1]=0;*/
   /*memset(&l_temp, 0, sizeof(l_temp));*/

/*_________DECREASE PLOTS NUMBER_________--*/

    /** rasc`y`t 14ti vnutrennih ry`ber i 15ti ry`ber na grana`h -
       - obsc`ityvaemye vsegda (dla` vseh kubov)*/
    /* vnutrennie ry`bra (14) */
    /* gc gf gh | gb ge gd fc fh hc */
    /* 00 01 02 | 03 04 05 03 04 05 */
    countSide2(fg, fc, xg, xc, yg, yc, zg, zc, Value, countCubNumber2(i, j, k,  0, p1), p1, 1, 1, bg, bc);
    countSide2(fg, ff, xg, xf, yg, yf, zg, zf, Value, countCubNumber2(i, j, k,  1, p1), p1, 0, 1, bg, bf);
    countSide2(fg, fh, xg, xh, yg, yh, zg, zh, Value, countCubNumber2(i, j, k,  2, p1), p1, 0, 1, bg, bh);

    if( (i+j+k)%2 == 0 )
    {
    countSide2(fg, fb, xg, xb, yg, yb, zg, zb, Value, countCubNumber2(i, j, k,  3, p1), p1, 0, 0, bg, bb);
    countSide2(fg, fe, xg, xe, yg, ye, zg, ze, Value, countCubNumber2(i, j, k,  4, p1), p1, 1, 0, bg, be);
    countSide2(fg, fd, xg, xd, yg, yd, zg, zd, Value, countCubNumber2(i, j, k,  5, p1), p1, 0, 0, bg, bd);
    } else
    {
    countSide2(ff, fc, xf, xc, yf, yc, zf, zc, Value, countCubNumber2(i, j, k,  3, p1), p1, 0, 0, bf, bc);
    countSide2(ff, fh, xf, xh, yf, yh, zf, zh, Value, countCubNumber2(i, j, k,  4, p1), p1, 0, 0, bf, bh);
    countSide2(fh, fc, xh, xc, yh, yc, zh, zc, Value, countCubNumber2(i, j, k,  5, p1), p1, 0, 0, bh, bc);
    }

/*    if(k==0)
 *   {
 */
	/* cd bc | bd ac */
	/* 06 07 | 08 08 */
    countSide2(fc, fd, xc, xd, yc, yd, zc, zd, Value, countCubNumber2(i, j, k,  6, p1), p1, 0, 1, bc, bd);
    countSide2(fb, fc, xb, xc, yb, yc, zb, zc, Value, countCubNumber2(i, j, k,  7, p1), p1, 1, 0, bb, bc);

    if( (i+j+k)%2 == 0 )
    {
    countSide2(fb, fd, xb, xd, yb, yd, zb, zd, Value, countCubNumber2(i, j, k,  8, p1), p1, 0, 0, bb, bd);
    } else
    {
    countSide2(fa, fc, xa, xc, ya, yc, za, zc, Value, countCubNumber2(i, j, k,  8, p1), p1, 0, 1, ba, bc);
    }
/*   }
 */

/*    if(j==0)
 *   {
 */
	/* bf fe be af */
	/* 09 10 11 11 */
    countSide2(fb, ff, xb, xf, yb, yf, zb, zf, Value, countCubNumber2(i, j, k,  9, p1), p1, 0, 0, bb, bf);
    countSide2(ff, fe, xf, xe, yf, ye, zf, ze, Value, countCubNumber2(i, j, k, 10, p1), p1, 0, 1, bf, be);
    if( (i+j+k)%2 == 0 )
    {
    countSide2(fb, fe, xb, xe, yb, ye, zb, ze, Value, countCubNumber2(i, j, k, 11, p1), p1, 1, 0, bb, be);
    } else
    {
    countSide2(fa, ff, xa, xf, ya, yf, za, zf, Value, countCubNumber2(i, j, k, 11, p1), p1, 0, 1, ba, bf);
    }
/*    }
 */

	/* hd he ed ha */
	/* 12 13 14 14 */
/*    if(i==0)
 *   {
 */                                                                
    countSide2(fh, fd, xh, xd, yh, yd, zh, zd, Value, countCubNumber2(i, j, k, 12, p1), p1, 0, 0, bh, bd);
    countSide2(fh, fe, xh, xe, yh, ye, zh, ze, Value, countCubNumber2(i, j, k, 13, p1), p1, 0, 0, bh, be);
    if( (i+j+k)%2 == 0 )
    {
    countSide2(fe, fd, xe, xd, ye, yd, ze, zd, Value, countCubNumber2(i, j, k, 14, p1), p1, 1, 1, be, bd);
    } else
    {
    countSide2(fh, fa, xh, xa, yh, ya, zh, za, Value, countCubNumber2(i, j, k, 14, p1), p1, 1, 1, bh, ba);
    }
/*    }
 */

/*    if((k==0)&&(j==0))*/
    countSide2(fa, fb, xa, xb, ya, yb, za, zb, Value, countCubNumber2(i, j, k, 15, p1), p1, 1, 0, ba, bb);
/*    if((k==0)&&(i==0))*/
    countSide2(fa, fd, xa, xd, ya, yd, za, zd, Value, countCubNumber2(i, j, k, 16, p1), p1, 0, 0, ba, bd);
/*    if((j==0)&&(i==0))*/                                         
    countSide2(fa, fe, xa, xe, ya, ye, za, ze, Value, countCubNumber2(i, j, k, 17, p1), p1, 0, 0, ba, be);


   decreasePlotsNumber();
   create_topology2(i,j,k,p1);
   return;
};

/**
 * Rasc`y`t otdelxnogo rebra: opredelenie iskomoi` pary
 */
void countSide(float fa, float fb, 
               float xa, float xb, 
               float ya, float yb, 
               float za, float zb, 
               float Value, int n, BigFilePointer *p1)
{
	// TODO ADD BOUNDARY PARAMETERS HERE !!!!
    if(((fa>Value)&&(fb>Value))||
       ((fa<Value)&&(fb<Value)))
        return;
    if((fa==Value)&&(fb==Value)) 
    {
        put(p1, xa, ya, za, n, false);/*skoree vsego e`to ne oc`enx udac`noe res`enie */
        put(p1, xb, yb, zb, n, false);
        /*printf("____adding edge %f %f %f %f %f %f %f %f %f\n", xa, ya, za, xb, yb, zb, fa, fb, Value);*/
        return;
    };
    if(fa==Value)
    {
        put(p1, xa, ya, za, n, false);
        /*printf("____adding vertex %f %f %f %f %f\n", xa, ya, za, fa, Value);*/
        return;
    };
    if(fb==Value)
    {
        put(p1, xb, yb, zb, n, false);
        /*printf("____adding vertex %f %f %f %f %f\n", xa, ya, za, fb, Value);*/
        return;
    };  
    put( p1,
         xa+(xb-xa)*(Value-fa)/(fb-fa),
         ya+(yb-ya)*(Value-fa)/(fb-fa),
         za+(zb-za)*(Value-fa)/(fb-fa),
         n, false);
};

void countSide2(float fa, float fb,
               float xa, float xb,
               float ya, float yb,
               float za, float zb,
               float Value, int n, BigFilePointer *p1,
               int is_a, int is_b, 
			   bool ba, bool bb)
{
    if(((fa>Value)&&(fb>Value))||
       ((fa<Value)&&(fb<Value)))
        return;
    if((fa==Value)&&(fb==Value))
    {
        if(is_a) put(p1, xa, ya, za, n, ba);
        if(is_b) put(p1, xb, yb, zb, n, bb);
        /*printf("____adding edge %f %f %f %f %f %f %f %f %f\n", xa, ya, za, xb, yb, zb, fa, fb, Value);*/
        return;
    };
    if(fa==Value)
    {
        if(is_a) put(p1, xa, ya, za, n, ba);
        /*printf("____adding vertex %f %f %f %f %f\n", xa, ya, za, fa, Value);*/
        return;
    };
    if(fb==Value)
    {
        if(is_b) put(p1, xb, yb, zb, n, bb);
        /*printf("____adding vertex %f %f %f %f %f\n", xa, ya, za, fb, Value);*/
        return;
    };
    put( p1,
         xa+(xb-xa)*(Value-fa)/(fb-fa),
         ya+(yb-ya)*(Value-fa)/(fb-fa),
         za+(zb-za)*(Value-fa)/(fb-fa),
         n,
		 (ba&&bb)
		 );
};

/**
 * Vyc`islenie topologii
 */
void create_topology(int i, int j, int k, BigFilePointer *p1)
{         
    int i_, ll, mm;
    int nplots[12];
    int temp_plot_number;
    int number_of_nplots, pyramid, edge;


    number_of_nplots = 0;
    for(pyramid = 0 ; pyramid < 24 ; ++pyramid)
    {
       for(edge = 0; edge < 6 ; ++edge)
       {
           temp_plot_number=countCubNumber(i, j, k, edge_array[pyramid][edge], p1);
           ll = is_a_plot( temp_plot_number , p1);
           if(ll!=-1)
           {
               nplots[number_of_nplots++] =1+ll+p1->bias;
               mm = is_next_plot(temp_plot_number, ll, p1);
               if( mm != -1 )
               {
                   nplots[number_of_nplots++] =1+mm+p1->bias;
               }
           }
/*********           else
*           {
*               for(i_=0;i_<n_temp;i_++)
*               {
*                   if(links[0][i_]==temp_plot_number)
*                   {
*                       nplots[number_of_nplots++] = 1+links[1][i] + p1->bias;
*                   }
*               }
*           }
**********/

       }

       switch (number_of_nplots) 
       {
           case 3:
               /*fprintf(p1->fp, "f %d %d %d\n", nplots[0], nplots[1], nplots[2]);*/
               addPoli( p1 , nplots[0], nplots[1], nplots[2]);
               break;
            
           case  4:
               /*addPoli( p1 , nplots[0], nplots[1], nplots[2]);
               addPoli( p1 , nplots[0], nplots[2], nplots[3]);
               break;
               */
           case  5:
           case  6:
           case  7:
           case  8:
           case  9:
           case 10:
           case 11:
           case 12:

               for(i_=1; i_<number_of_nplots-1;i_++)
               {
                   /*fprintf(p1->fp,"f %d %d %d\n", nplots[i_], nplots[i_+1], nplots[i_+2]);*/
                   addPoli(p1, nplots[0], nplots[i_], nplots[i_+1]);
               }

               break;
              
           case 2:           
             /*  fprintf(p1->fp, "f %d %d %d\n", nplots[0], nplots[1], nplots[0]);*/
               addPoli(p1, nplots[0], nplots[1], nplots[0]);
               break;
       }
       
       number_of_nplots=0;                   
    }
    /*for(i_=1;i_<=number_of_nplots;i_++)
     *   fprintf(p1->fp, "f %d %d %d\n", i_, i_, i_);
     */

    p1->bias += p1->plots_number;
    return;
};

/**
 * Vyc`islenie topologii
 */
void create_topology2(int i, int j, int k, BigFilePointer *p1)
{         
    int i_, ll, mm;
    int nplots[12];
//	bool boundary_nplots[12];
    int temp_plot_number;
    int number_of_nplots, pyramid, edge;
    int even_odd = (i+j+k)%2;

    /*number_of_nplots = 0;*/
    for(pyramid = 0 ; pyramid < 5 ; ++pyramid)
    {
		number_of_nplots=0;       
//		number_of_boundary_nplots=0;       
       for(edge = 0; edge < 6 ; ++edge)
       {		   
           temp_plot_number=countCubNumber2(i, j, k, edge_array2[even_odd][pyramid][edge], p1);
           ll = is_a_plot( temp_plot_number , p1);
           if(ll!=-1)
           {
               nplots[number_of_nplots++] =1+ll+p1->bias;
//			   boundary_nplots[number_of_nplots-1]=is_a_boundary_plot( ll , p1) ;

               mm = is_next_plot(temp_plot_number, ll, p1);
               if( mm != -1 )
               {
                   nplots[number_of_nplots++] =1+mm+p1->bias;
//				   boundary_nplots[number_of_nplots-1]=is_a_boundary_plot( mm , p1) ;
               }
           }
/*********           else
*           {
*               for(i_=0;i_<n_temp;i_++)
*               {
*                   if(links[0][i_]==temp_plot_number)
*                   {
*                       nplots[number_of_nplots++] = 1+links[1][i] + p1->bias;
*                   }
*               }
*           }
**********/

       }

       switch (number_of_nplots) 
       {
           case 3:
               addPoli( p1 , 
				   nplots[0],
				   nplots[1],
				   nplots[2]
				   );
               break;
            
           case  4:
           case  5:
           case  6:
           case  7:
           case  8:
           case  9:
           case 10:
           case 11:
           case 12:

               for(i_=1; i_<number_of_nplots-1;i_++)
               {
                   addPoli(p1, 
					   nplots[0],
					   nplots[i_],
					   nplots[i_+1]
					   );
               }

               break;
              
           case 2:
               addPoli(p1, 
				   nplots[0],
				   nplots[1],
				   nplots[0]
				   );
               break;

		   default:
			   break;

       }
    }

    p1->bias += p1->plots_number;
    return;
};

//bool is_a_boundary_plot(int index, BigFilePointer *p1)
//{
//	return p1->plots.boundary[index];
//}

int is_a_plot(int plot, BigFilePointer *p1)
{
    int i;

    for( i = 0 ; i < p1->plots_number ; ++i )
    {
        if(p1->plots[i] == plot)
            return i;
    }
    return -1;
}

int is_next_plot(int plot, int number, BigFilePointer *p1)
{
	if( (number+1) >= p1->plots_number )
		return -1;

	if(p1->plots[number+1] == plot)
		return (number+1);
	else
		return -1;
}


/**
 * Vyc`islenie nomera rebra
 */
int countCubNumber(int i, int j, int k, int edgeNumber, BigFilePointer *p1)
{            /*?????????*/
    return (50*(k+p1->MAXk*(j+p1->MAXj*i)) + edgeNumber);
};

int countCubNumber2(int i, int j, int k, int edgeNumber, BigFilePointer *p1)
{            /*?????????*/
    return (18*(k+p1->MAXk*(j+p1->MAXj*i)) + edgeNumber);
};
/*
*
*
*
*
*
*
*
*
*/
//@@Iak 080720 #define WRITE_BOUNDARY

void sendAll2_inner(BigFilePointer *p1, int cMethod, float cParams)
{
//	int msgsock;

    int i, j, *memInt;
//    int ii; //, kk;
    float *fpool, *fpoolseek;
	int	  *fpoli, *fpoliseek;
	int	  *pBound_pool, *pBound_seek;
	int cpCounter=0, cbCounter=0;
	int plotsInPack, curBlockSize, trianglesInPack;

#ifdef WRITE_BOUNDARY
	FILE *f_boundary=NULL;
	int c_boundary_plots=0;
	int rank;
	MPI_Comm_rank( MPI_COMM_WORLD, &rank );
	char cBoundaryWFFName[1024];
	sprintf(cBoundaryWFFName, "boundary%3d.wff", rank);
	f_boundary = fopen(cBoundaryWFFName, "w");
#endif

// lira	memInt = (int *)malloc(sizeof(float));
//MPI_Barrier(MPI_COMM_WORLD);
	memInt = (int *)malloc(sizeof(int));

	/* PACKING X,Y,Z information */
	p1->temp = p1->head;
	plotsInPack=0;
	for(i = 0 ; i < (p1->stackSize) ; ++i)
	{
		if( i != (p1->stackSize)-1 )
		{
			plotsInPack += Number ;
		}
		else
		{
			plotsInPack += (p1->filledSize) ;
		}
		p1->temp=p1->temp->p;
	}
// lira	fpool = (float *)malloc( 3 * plotsInPack * sizeof(float) );
	fpool = alloc_float_mas_n1( 3 * plotsInPack );
	fpoolseek = fpool;

	pBound_pool=(int*)malloc(p1->cBoundaryPlots*sizeof(int));
	pBound_seek=pBound_pool;

	p1->temp = p1->head;
	for(i = 0 ; i < (p1->stackSize) ; ++i)
	{
		if( i != (p1->stackSize)-1 )
		{
			curBlockSize = Number ;
		}
		else
		{
			curBlockSize = (p1->filledSize) ;
		}
		for(j=0;j<curBlockSize;j++)
		{
			fpoolseek[j              ]=p1->temp->x[j];
			fpoolseek[j+plotsInPack  ]=p1->temp->y[j];
			fpoolseek[j+2*plotsInPack]=p1->temp->z[j];
//ToDo			fpoolseek[j+3*plotsInPack]=p1->temp->b[j];
/* 010427_18.50			fpoolseek[j+3*plotsInPack]=(float)p1->temp->l[j];
*/
			if((p1->temp->b[j])) {
				(*pBound_seek)=cpCounter;
				pBound_seek++;
				cbCounter++; // debug - remove
			}
// kp97 050814 21:35
#ifdef WRITE_BOUNDARY
			if(f_boundary) {
				if(p1->temp->b[j]) {
					fprintf(f_boundary,"v %e %e %e\n", p1->temp->x[j], p1->temp->y[j], p1->temp->z[j]);
					c_boundary_plots++;
				}
			}
#endif
			cpCounter++;
		}
		fpoolseek+=curBlockSize;
		p1->temp=p1->temp->p;
	}

#ifdef WRITE_BOUNDARY
	{
		if(f_boundary) {
			for(int a2=0; a2<c_boundary_plots; a2++)
				fprintf(f_boundary,"f %d %d %d\n", a2+1, a2+1, a2+1);
			fclose(f_boundary);
		}
	}
#endif

	//printf("nbounds=%d and added=%d\n", p1->cBoundaryPlots, cbCounter);


	/* PACKING TRIANGLES INFORMATION */
    p1->poli_temp = p1->poli_head;
	trianglesInPack=0;
    for(i = 0 ; i < (p1->poli_stackSize) ; ++i)
    {
        if( i != (p1->poli_stackSize)-1 )
        { 
            trianglesInPack += POLI_SIZE ;
        }
        else
        {
            trianglesInPack += (p1->poli_filledSize) ;
        }
        p1->poli_temp=p1->poli_temp->p;
    }
	fpoli=(int*)malloc(trianglesInPack*sizeof(int));
	fpoliseek=fpoli;

    p1->poli_temp = p1->poli_head;
    for(i = 0 ; i < (p1->poli_stackSize) ; ++i)
    {
        if( i != (p1->poli_stackSize)-1 )
        { 
            curBlockSize = POLI_SIZE ;
        }
        else
        {
            curBlockSize = (p1->poli_filledSize) ;
        }
		for(j=0;j<curBlockSize;j++)
		{			
			fpoliseek[j]=p1->poli_temp->pool[j];			
		}
		fpoliseek+=curBlockSize;
        p1->poli_temp=p1->poli_temp->p;
    }
/*
    {
    float xMin, xMax, yMin, yMax, zMin, zMax;
	    xMin=fpool[0];xMax=fpool[0];
	    yMin=fpool[plotsInPack];yMax=fpool[plotsInPack];
	    zMin=fpool[plotsInPack*2];zMax=fpool[plotsInPack*2];
	    for(ii=0; ii<plotsInPack; ii++)
	    {
    		if(xMin>fpool[ii])
    			xMin=fpool[ii];
	    	else if(xMax<fpool[ii])
    			xMax=fpool[ii];

    		if(yMin>fpool[ii+plotsInPack])
    			yMin=fpool[ii+plotsInPack];
	    	else if(yMax<fpool[ii+plotsInPack])
    			yMax=fpool[ii+plotsInPack];

    		if(zMin>fpool[ii+plotsInPack*2])
    			zMin=fpool[ii+plotsInPack*2];
	    	else if(zMax<fpool[ii+plotsInPack*2])
    			zMax=fpool[ii+plotsInPack*2];
	    }
    	fprintf(stderr, "kp97_2: %f %f %f %f %f %f\n",xMin, xMax, yMin, yMax, zMin, zMax);
    }
*/
#define WRITE_COMPRESSION_DEBUG
#ifdef WRITE_COMPRESSION_DEBUG
    {
    FILE * fp1;
    fp1 = fopen("050815_001.wff", "w");
    for(int a1=0; a1<plotsInPack; a1++)
	fprintf(fp1,"v %e %e %e\n", fpool[a1], fpool[a1+plotsInPack], fpool[a1+2*plotsInPack]);
    for(int a2=0; a2<trianglesInPack; a2+=3)
	fprintf(fp1,"f %d %d %d\n", fpoli[a2], fpoli[a2+1], fpoli[a2+2]);
    fclose(fp1);
    }
#endif
//010723    printf("start compression\n");

	unsigned long t1, t2;

#ifndef KP_UNIX
t1=timeGetTime();
#endif
//printf("time %lu\n", t3);
    trianglesInPack/=3;
    if(p1->MAXk==2) plotsInPack=-plotsInPack;
//////////////////////////////
///////////////////////////////
//printf("slave: using compression method=%d with param=%f\n", cMethod, cParams);
	if( cMethod==lira00Compression ) {
		//lira00SurfCompress(&fpool, &plotsInPack, &fpoli, &trianglesInPack);
	} else if( cMethod==serge00Compression ) {
		serge00SurfCompress(fpool, plotsInPack, fpoli, trianglesInPack, pBound_pool, p1->cBoundaryPlots, cParams);
	} else if( cMethod==noCompression ) {
		// no compression
	} else {
		// unknown compression method ....
	}

    trianglesInPack*=3;
#ifndef KP_UNIX
t2=timeGetTime();
//printf("_compress_time %lu\n", t2-t1);
#endif    

#ifdef WRITE_COMPRESSION_DEBUG
    {
    FILE * fp1;
    fp1 = fopen("050815_002.wff", "w");
    for(int a1=0; a1<plotsInPack; a1++)
	fprintf(fp1,"v %e %e %e\n", fpool[a1], fpool[a1+plotsInPack], fpool[a1+2*plotsInPack]);
    for(int a2=0; a2<trianglesInPack; a2+=3)
	fprintf(fp1,"f %d %d %d\n", fpoli[a2], fpoli[a2+1], fpoli[a2+2]);
    fclose(fp1);
    }
#endif
//010723    printf("comp ok\n");
/*!!!!___IT IS EXTREMELY NESSESARY TO REPACK fpoli array of INT's here_____!!!!!!!!*/
    /*------------------------------------------
    * 1. pereday`m klientu c`islo "oblastei`"
    */

/*	*memInt = 1;
	sendNcharBytes(msgsock, (char *)memInt, 4);

	*memInt = plotsInPack * 3 * sizeof(float);
	sendNcharBytes(msgsock, (char*)memInt, 4);
	
	if(*memInt != sendNcharBytes(msgsock, (char*)fpool, *memInt) )
                printf("error sending fpool %d\n", *memInt);
*/    
	*memInt = plotsInPack * 3;
	MPI_Send(memInt,      1, MPI_INT,   0, 0, MPI_COMM_WORLD );
    MPI_Send(fpool, *memInt, MPI_FLOAT, 0, 0, MPI_COMM_WORLD );
    /*
	* 4. pereday`m klientu c`islo "oblastei`" s poligonami 
	*/
/*
    *memInt = 1;
    sendNcharBytes(msgsock, (char *)memInt, 4);

    *memInt = trianglesInPack * sizeof(int);
    sendNcharBytes(msgsock, (char *)memInt, 4);
	
	/// * 6. pereday`m oblasti   
	///// ******************!!!!!!!!!!!!!!!!!!!!!!!!!!!!!11*********
	if(*memInt != sendNcharBytes(msgsock, (char*)fpoli, *memInt) )
            printf("error sending poli_pool\n");;
*/

    *memInt = trianglesInPack ;
	MPI_Send(memInt,      1, MPI_INT,   0, 0, MPI_COMM_WORLD );
    MPI_Send(fpoli, *memInt, MPI_INT, 0, 0, MPI_COMM_WORLD );

	//ToDo
	// send in-boundary plots to server: pBound_pool, p1->cBoundaryPlots
    *memInt = p1->cBoundaryPlots ;
	MPI_Send(memInt,      1, MPI_INT,   0, 0, MPI_COMM_WORLD );
	if(p1->cBoundaryPlots)
		MPI_Send(pBound_pool, *memInt, MPI_INT, 0, 0, MPI_COMM_WORLD );

//010723    printf("send ok\n");
    /*printf("trying to free memory\n");*/
	free(pBound_pool);
    free(memInt);
    free(fpool);free(fpoli);
    freeMemory(p1);
    /*printf("memory free OK!\n");*/

    return;
}

void stopSending_inner()
{
    int *memInt;
   /*printf("stopSending started\n");*/
   memInt = (int *)malloc(sizeof(int));
   *memInt =0;
	MPI_Send(memInt,      1, MPI_INT,   0, 0, MPI_COMM_WORLD );
   free(memInt);
   return;
}

void decreasePlotsNumber()
{
}
